/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-07-21     96975       the first version
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include "board_adc_poll.h"
#include <stdio.h>

#define ADC_DEV_NAME        "adc2"      /* ADC 设备名称 */
#define ADC_DEV_CHANNEL     0           /* ADC 通道 */
#define REFER_VOLTAGE       3300         /* 参考电压 3.3V,数据精度乘以1000保留3位小数*/
#define ADC_CONVERT_BITS    0xFFFF      /* 转换位数为16位 */


static rt_uint8_t s_adc[16] = {0};

int copyAdc(rt_uint8_t* dst)
{
    memcpy(dst, s_adc, 16);
    return 16;
}

static void boardADC_Switch(uint8_t ch)
{
    switch(ch)
    {
    case 0:
        rt_pin_write(ADCSWITCH3_PIN, PIN_LOW);
        rt_pin_write(ADCSWITCH2_PIN, PIN_LOW);
        rt_pin_write(ADCSWITCH1_PIN, PIN_LOW);
        break;
    case 1:
        rt_pin_write(ADCSWITCH3_PIN, PIN_LOW);
        rt_pin_write(ADCSWITCH2_PIN, PIN_LOW);
        rt_pin_write(ADCSWITCH1_PIN, PIN_HIGH);
        break;
    case 2:
        rt_pin_write(ADCSWITCH3_PIN, PIN_LOW);
        rt_pin_write(ADCSWITCH2_PIN, PIN_HIGH);
        rt_pin_write(ADCSWITCH1_PIN, PIN_LOW);
        break;
    case 3:
        rt_pin_write(ADCSWITCH3_PIN, PIN_LOW);
        rt_pin_write(ADCSWITCH2_PIN, PIN_HIGH);
        rt_pin_write(ADCSWITCH1_PIN, PIN_HIGH);
        break;
    case 4:
        rt_pin_write(ADCSWITCH3_PIN, PIN_HIGH);
        rt_pin_write(ADCSWITCH2_PIN, PIN_LOW);
        rt_pin_write(ADCSWITCH1_PIN, PIN_LOW);
        break;
    case 5:
        rt_pin_write(ADCSWITCH3_PIN, PIN_HIGH);
        rt_pin_write(ADCSWITCH2_PIN, PIN_LOW);
        rt_pin_write(ADCSWITCH1_PIN, PIN_HIGH);
        break;
    case 6:
        rt_pin_write(ADCSWITCH3_PIN, PIN_HIGH);
        rt_pin_write(ADCSWITCH2_PIN, PIN_HIGH);
        rt_pin_write(ADCSWITCH1_PIN, PIN_LOW);
        break;
    case 7:
        rt_pin_write(ADCSWITCH3_PIN, PIN_HIGH);
        rt_pin_write(ADCSWITCH2_PIN, PIN_HIGH);
        rt_pin_write(ADCSWITCH1_PIN, PIN_HIGH);
        break;
    }
}

int boardADC_Init(void)
{
    rt_pin_mode(ADCSWITCH1_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(ADCSWITCH2_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(ADCSWITCH3_PIN, PIN_MODE_OUTPUT);

    return RT_EOK;
}
INIT_ENV_EXPORT(boardADC_Init);


//
//static rt_uint16_t toFloat16(float_t f)
//{
//    rt_uint32_t* i = (rt_uint32_t*)&f;
//    rt_uint32_t s = (*i>>31)&0x01;
//    rt_uint32_t e = ((*i>>23)&0xff) - 0x7f;
//    rt_uint32_t m = (*i)&0x7fffff;
//
//    e += 7;
//    rt_uint16_t ret = ((s&0x0x)<<15);
//    ret |= (e&0xf) << 11;
//    ret |= (m>>13)&0x7ff;
//    return ret;
//}
//




static void float2uint16(float f, rt_uint8_t* highByte, rt_uint8_t* lowByte)
{
    rt_uint8_t high = (rt_int8_t)f;
    if (f < 0)
    {
        f *= -1;
    }

    f *= 100;
    rt_uint8_t low = (int)f % 100;

    *highByte = high;
    *lowByte = low;
}


rt_uint32_t getMax(rt_uint32_t* arr, int len)
{
    rt_uint32_t m = arr[0];
    for (int i=1; i<len; ++i)
    {
        if (arr[i] > m)
        {
            m = arr[i];
        }
    }

    return m;
}

rt_uint32_t getMin(rt_uint32_t* arr, int len)
{
    rt_uint32_t m = arr[0];
    for (int i=1; i<len; ++i)
    {
        if (arr[i] < m)
        {
            m = arr[i];
        }
    }

    return m;
}

rt_uint32_t getAve(rt_uint32_t* arr, int len)
{
    rt_uint64_t sum64 = 0;
    for (int i=0; i<len; ++i)
    {
        sum64 += arr[i];
    }
    sum64 -= getMax(arr, len);
    sum64 -= getMin(arr, len);
    rt_uint32_t ret = sum64;
    ret /= (len-2);

    return ret;
}


float getRealVin(float vol)
{
    float ret = 0.0;
    if (vol < 1.25) // negative
    {
        ret = -11.0*(4*vol - 5);
    }
    else
    {
        ret = 11.0*(4*vol - 5);
    }

    return ret;
}


static rt_uint32_t s_arr10[10] = {0};

static int adc_vol_sample(int argc, char *argv[])
{
    rt_adc_device_t adc_dev;
    rt_uint32_t value, vol;
    rt_err_t ret = RT_EOK;

    /* 查找设备 */
    adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
    if (adc_dev == RT_NULL)
    {
        rt_kprintf("adc sample run failed! can't find %s device!\n", ADC_DEV_NAME);
        return RT_ERROR;
    }

    /* 使能设备 */
    ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);

    for (rt_uint8_t adcI=0; adcI<8; ++adcI )
    {
        boardADC_Switch(adcI);

        rt_thread_mdelay(3);

        for (int i=0; i<10; ++i)
        {
            /* 读取采样值 */
            value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
            s_arr10[i] = value;
        }

        value = getAve(s_arr10, 10);
        rt_kprintf("the ave value is :%d \n", value);

        /* 转换为对应电压值 */
        vol = value * REFER_VOLTAGE / ADC_CONVERT_BITS;
        rt_kprintf("the voltage is :%d.%03d \n", vol / 1000, vol % 1000);

        float fVol = vol;
        fVol /= 1000.0;

        float realVol = getRealVin(fVol);
        rt_kprintf("real voxl: %f \n\n", realVol);
    }



    /* 关闭通道 */
//    ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);

    return ret;
}













static void adc_thread_entry(void *parameter)
{
    rt_adc_device_t adc_dev;
    rt_uint32_t value, vol;
    adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
    /* 查找设备 */
    if (adc_dev == RT_NULL)
    {
        rt_kprintf("adc sample run failed! can't find %s device!\n", ADC_DEV_NAME);
        return;
    }
    /* 使能设备 */
    rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);

    while (1)
    {
        for (rt_uint8_t adcI=0; adcI<8; ++adcI )
        {
            boardADC_Switch(adcI);

//            rt_thread_mdelay(10);

//            for (int i=0; i<3; ++i)
//            {
//                /* 读取采样值 */
//                value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
//                s_arr10[i] = value;
//            }
//
//            value = getAve(s_arr10, 3);
//            rt_kprintf("the ave value is :%d \n", value);

            value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);

            /* 转换为对应电压值 */
            vol = value * REFER_VOLTAGE / ADC_CONVERT_BITS;
//            rt_kprintf("the voltage is :%d.%03d \n", vol / 1000, vol % 1000);

            float fVol = vol;
            fVol /= 1000.0;

            float realVol = getRealVin(fVol);

//            float2uint16(realVol, s_adc+14-2*adcI, s_adc+15-2*adcI);
            float2uint16(realVol, s_adc+2*adcI, s_adc+1+2*adcI);

//            rt_kprintf(" index: %d, real voxl: %f \n", adcI, realVol);
        }

//        rt_kprintf("one loop of adc\n\n");
    }
}



int startAdcThread()
{
    rt_err_t ret = RT_EOK;
    /* 创建 serial 线程 */
    rt_thread_t thread = rt_thread_create("tADC", adc_thread_entry, RT_NULL, 1024, 25, 10);
    /* 创建成功则启动线程 */
    if (thread != RT_NULL)
    {
        rt_kprintf("start adc thread ok\n");
        rt_thread_startup(thread);
    }
    else
    {
        rt_kprintf("start adc thread failed\n");
        ret = RT_ERROR;
    }


    return ret;
}


















/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(adc_vol_sample, adc voltage convert sample);
